
Namespace std

    Public Class sortset(Of keyType As IComparable(Of keyType))
        Inherits xtree(Of keyType)

        Default Public ReadOnly Property data(ByVal index As Int32) As keyType
            Get
                Dim rtn As iterator = Nothing
                rtn = New iterator(root)
                rtn += index
                Return (+rtn)
            End Get
        End Property
    End Class

    Public Class [set](Of keyType As IComparable(Of keyType))
        Inherits sortset(Of signednode(Of keyType))

        Private _signingIndex As Int32

        Public Shadows Class iterator
            Inherits sortset(Of signednode(Of keyType)).iterator

            Public Sub New()
                MyBase.New()
            End Sub

            Public Sub New(ByVal i As pointer(Of node))
                MyBase.New(i)
            End Sub

            Public Overloads Shared Operator +(ByVal this As iterator) As keyType
                Return ++convertor.cast(Of sortset(Of signednode(Of keyType)).iterator)(this)
            End Operator
        End Class

        Public Overloads Function begin() As iterator
            Return New iterator(MyBase.begin())
        End Function

        Public Overloads Function [end]() As iterator
            Return New iterator(MyBase.end())
        End Function

        Public Overloads Function rbegin() As iterator
            Return New iterator(MyBase.rbegin())
        End Function

        Public Overloads Function rend() As iterator
            Return New iterator(MyBase.rend())
        End Function

        Public Shadows Function insert(ByVal k As keyType) As iterator
            Dim sk As signednode(Of keyType) = Nothing
            sk = New signednode(Of keyType)(_signingIndex)
            sk.key = k

            Return New iterator(MyBase.insert(sk))
        End Function

        Public Shadows Function insert(ByVal i As [set](Of keyType)) As Boolean
            If i Is Nothing Then
                Return False
            Else
                Dim j As [set](Of keyType).iterator = Nothing
                j = i.begin()
                While j <> i.end()
                    If insert(+j) = [end]() Then
                        Return False
                    End If
                    j += 1
                End While

                Return True
            End If
        End Function

        Public Shadows Function [erase](ByVal k As keyType) As Boolean
            Dim sk As signednode(Of keyType) = Nothing
            sk = New signednode(Of keyType)(_signingIndex)
            sk.key = k

            Return MyBase.erase(sk)
        End Function

        Public Shadows Function [find](ByVal k As keyType) As iterator
            Dim sk As signednode(Of keyType) = Nothing
            sk = New signednode(Of keyType)(_signingIndex)
            sk.key = k

            Return New iterator(MyBase.find(sk))
        End Function

        Public Overrides Function clone() As Object
            Dim rtn As [set](Of keyType) = Nothing
            rtn = MyBase.clone()
            rtn._signingIndex = _signingIndex
            Return rtn
        End Function

        Public Sub New()
            MyBase.new()
            _signingIndex = rnd(0, _signing.maxSigningIndex, True)
        End Sub

        Public Shared Sub initial_instance(ByRef i As [set](Of keyType))
            If i Is Nothing Then
                i = New [set](Of keyType)()
            Else
                i.clear()
            End If
        End Sub

        Private Class unittestInfo
            Public s As [set](Of keyType) = Nothing
            Public keys As vector(Of keyType) = Nothing

            Public Sub New()
                s = New [set](Of keyType)()
                keys = New vector(Of keyType)()
            End Sub
        End Class

        Private Class unittestActions
            Private Shared Sub parseParameter(ByVal obj As Object _
                                              , ByRef s As [set](Of String) _
                                              , ByRef keys As vector(Of String))
                Dim info As [set](Of String).unittestInfo = Nothing
                info = convertor.cast(Of [set](Of String).unittestInfo)(obj)
                s = info.s
                keys = info.keys

                assert(Not s Is Nothing, "set is nothing.")
                assert(Not keys Is Nothing, "keys is nothing.")
            End Sub

            Public Shared Sub [erase](ByVal obj As Object)
                Dim s As [set](Of String) = Nothing
                Dim keys As vector(Of String) = Nothing
                parseParameter(obj, s, keys)

                If Not keys.empty() Then
                    Dim i As Int64
                    i = rnd(0, keys.size(), True)
                    assert(s.erase(keys(i)), "s.erase(" + keys(i) + ") returns false.")
                    assert(s.find(keys(i)) = s.end(), "s.find(" + keys(i) + ") <> s.end()")
                    raiseError("erase " + keys(i))
                    keys.erase(i)
                Else
                    assert(s.empty(), "s.empty() <> keys.empty().")
                End If
            End Sub

            Public Shared Sub find(ByVal obj As Object)
                Dim s As [set](Of String) = Nothing
                Dim keys As vector(Of String) = Nothing
                parseParameter(obj, s, keys)

                If Not keys.empty() Then
                    Dim i As Int64
                    i = rnd(0, keys.size(), True)
                    assert(s.find(keys(i)) <> s.end(), "s.find(" + keys(i) + ") = s.end()")
                    raiseError("find " + keys(i))
                Else
                    assert(s.empty(), "s.empty() <> keys.empty().")
                End If
            End Sub

            Public Shared Sub insert(ByVal obj As Object)
                Dim s As [set](Of String) = Nothing
                Dim keys As vector(Of String) = Nothing
                parseParameter(obj, s, keys)

                Dim k As String = Nothing
                k = createGUID()
                assert(s.insert(k) = s.find(k), "s.insert(" + k + ") <> s.find")
                raiseError("insert " + k)
                keys.push_back(k)
            End Sub

            Public Shared Sub clone(ByVal obj As Object)
                Dim s As [set](Of String) = Nothing
                parseParameter(obj, s, Nothing)

                Dim info As [set](Of String).unittestInfo = Nothing
                info = convertor.cast(Of [set](Of String).unittestInfo)(obj)
                Dim oldset As [set](Of String) = Nothing
                oldset = info.s
                info.s = Nothing
                copy(info.s, s)
                assert(Not Object.ReferenceEquals(info.s, oldset), "cannot clone to a new instance.")
                raiseError("clone a same instance with existing one.")
            End Sub

            Public Shared Sub clear(ByVal obj As Object)
                Dim s As [set](Of String) = Nothing
                Dim keys As vector(Of String) = Nothing
                parseParameter(obj, s, keys)

                s.clear()
                assert(s.size() = 0, "s.size()<>0 after clear.")
                keys.clear()
            End Sub
        End Class

        Public Shared Sub automaticalUnittest()
            Dim roundcount As Int64 = 10240
            If isreleasebuild() Then
                roundcount *= 20
            End If

            raiseError("********** set(of string) automatcial unittest **********", errorHandle.errorType.application)

            Dim info As unittestInfo = Nothing
            info = New unittestInfo()
            randomrun.invoke(roundcount, info _
                             , New randomrun.info(0.43, AddressOf unittestActions.insert) _
                             , New randomrun.info(0.25, AddressOf unittestActions.find) _
                             , New randomrun.info(0.26, AddressOf unittestActions.erase) _
                             , New randomrun.info(0.01, AddressOf unittestActions.clone) _
                             , New randomrun.info(0.05, AddressOf unittestActions.clear))
            While Not info.keys.empty()
                unittestActions.erase(info)
            End While

            raiseError("************** finish automatical unittest **************", errorHandle.errorType.application)
        End Sub

        Private Class perftestActions
            Private Shared Sub parseParameter(ByVal obj As Object, ByRef s As [set](Of String))
                s = convertor.cast(Of [set](Of String))(obj)
                assert(Not s Is Nothing, "s is nothing.")
            End Sub

            Public Shared Sub insert(ByVal obj As Object)
                Dim s As [set](Of String) = Nothing
                parseParameter(obj, s)

                raiseError("insert")
                s.insert(createGUID())
            End Sub

            Public Shared Sub find(ByVal obj As Object)
                Dim s As [set](Of String) = Nothing
                parseParameter(obj, s)

                raiseError("find")
                s.find(createGUID())
            End Sub

            Public Shared Sub [erase](ByVal obj As Object)
                Dim s As [set](Of String) = Nothing
                parseParameter(obj, s)

                raiseError("erase")
                s.erase(createGUID())
            End Sub

            Public Shared Sub clone(ByVal obj As Object)
                Dim s As [set](Of String) = Nothing
                parseParameter(obj, s)

                raiseError("clone")
                Dim s2 As [set](Of String) = Nothing
                copy(s2, s)
            End Sub

            Public Shared Sub clear(ByVal obj As Object)
                Dim s As [set](Of String) = Nothing
                parseParameter(obj, s)

                raiseError("clear")
                s.clear()
            End Sub
        End Class

        Public Shared Sub performanceTest()
            Dim roundcount As Int64 = 102400
            If isreleasebuild() Then
                roundcount *= 20
            End If

            raiseError("********** set(of string) automatcial perftest **********", errorHandle.errorType.application)

            Dim s As [set](Of String) = Nothing
            s = New [set](Of String)()
            randomrun.invoke(roundcount, s _
                             , New randomrun.info(0.43, AddressOf perftestActions.insert) _
                             , New randomrun.info(0.25, AddressOf perftestActions.find) _
                             , New randomrun.info(0.26, AddressOf perftestActions.erase) _
                             , New randomrun.info(0.01, AddressOf perftestActions.clone) _
                             , New randomrun.info(0.05, AddressOf perftestActions.clear))

            raiseError("************** finish automatical perftest **************", errorHandle.errorType.application)
        End Sub

        Public Shared Sub performanceTest2()
            Dim roundcount As Int64 = 10240
            If isreleasebuild() Then
                roundcount *= 5
            End If

            raiseError("********** set(of string) automatcial perftest2 **********", errorHandle.errorType.application)
            Dim s As [set](Of String) = Nothing
            s = New [set](Of String)()
            While roundcount > 0
                s.insert(createGUID())
                roundcount -= 1
            End While

            Dim s2 As [set](Of String) = Nothing
            s2 = New [set](Of String)()
            While s2._signingIndex = s._signingIndex
                s2 = New [set](Of String)()
                raiseError("new allocate set(of string)", errorHandle.errorType.warning)
            End While
            Dim it As [set](Of String).iterator = Nothing
            it = s.begin()
            While it <> s.end()
                s2.insert(+it)
                it += 1
            End While
            raiseError("************** finish automatical perftest2 **************", errorHandle.errorType.application)
        End Sub
    End Class

End Namespace
